#include "wc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void init_stats(Stats *stats) {
    stats->chars = 0;
    stats->words = 0;
    stats->sentences = 0;
    stats->lines = 0;
    stats->code_lines = 0;
    stats->empty_lines = 0;
    stats->comment_lines = 0;
}

int count_chars(const char *filename) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Failed to open file");
        return -1;
    }

    int count = 0;
    int c;
    while ((c = fgetc(file)) != EOF) {
        count++;
    }

    fclose(file);
    return count;
}

int count_words(const char *filename) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Failed to open file");
        return -1;
    }

    int count = 0;
    int in_word = 0;
    int c;

    while ((c = fgetc(file)) != EOF) {
        if (isalpha(c)) {
            if (!in_word) {
                count++;
                in_word = 1;
            }
        } else {
            in_word = 0;
        }
    }

    fclose(file);
    return count;
}

int count_sentences(const char *filename) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Failed to open file");
        return -1;
    }

    int count = 0;
    int c;

    while ((c = fgetc(file)) != EOF) {
        if (c == '.' || c == '!' || c == '?') {
            count++;
        }
    }

    fclose(file);
    return count;
}

void count_basic(const char *filename, Stats *stats) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Failed to open file");
        return;
    }

    int c;
    int in_word = 0;
    
    while ((c = fgetc(file)) != EOF) {
        stats->chars++;
        
        // Count words
        if (isalpha(c)) {
            if (!in_word) {
                stats->words++;
                in_word = 1;
            }
        } else {
            in_word = 0;
        }
        
        // Count sentences
        if (c == '.' || c == '!' || c == '?') {
            stats->sentences++;
        }
        
        // Count lines
        if (c == '\n') {
            stats->lines++;
        }
    }
    
    // Last line might not have a newline character
    if (stats->chars > 0 && stats->lines == 0) {
        stats->lines = 1;
    }

    fclose(file);
}

void count_extended(const char *filename, Stats *stats) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Failed to open file");
        return;
    }

    char line[1024];
    int in_comment_block = 0;
    
    while (fgets(line, sizeof(line), file)) {
        stats->lines++;
        int len = strlen(line);
        int is_empty = 1;
        int is_comment = 0;
        int has_code = 0;
        
        // Check for empty line
        for (int i = 0; i < len; i++) {
            if (!isspace((unsigned char)line[i])) {
                is_empty = 0;
                break;
            }
        }
        
        if (is_empty) {
            stats->empty_lines++;
            continue;
        }
        
        // Check for comment lines and code lines
        for (int i = 0; i < len; i++) {
            if (in_comment_block) {
                is_comment = 1;
                // Check for end of multi-line comment
                if (line[i] == '*' && i+1 < len && line[i+1] == '/') {
                    in_comment_block = 0;
                    i++;
                    // Check if there's code after the comment
                    for (int j = i+1; j < len; j++) {
                        if (!isspace((unsigned char)line[j])) {
                            has_code = 1;
                            break;
                        }
                    }
                }
            } else {
                // Check for single-line comment
                if (line[i] == '/' && i+1 < len && line[i+1] == '/') {
                    is_comment = 1;
                    break;
                }
                // Check for start of multi-line comment
                else if (line[i] == '/' && i+1 < len && line[i+1] == '*') {
                    is_comment = 1;
                    in_comment_block = 1;
                    i++;
                }
                // Check if there's code
                else if (!isspace((unsigned char)line[i])) {
                    has_code = 1;
                }
            }
        }
        
        if (is_comment) {
            stats->comment_lines++;
        }
        if (has_code) {
            stats->code_lines++;
        }
    }

    fclose(file);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s [option] [filename]\n", argv[0]);
        fprintf(stderr, "Options:\n");
        fprintf(stderr, "  -c    Count characters\n");
        fprintf(stderr, "  -w    Count words\n");
        fprintf(stderr, "  -s    Count sentences\n");
        fprintf(stderr, "  -l    Count lines\n");
        fprintf(stderr, "  -cl   Count code lines\n");
        fprintf(stderr, "  -el   Count empty lines\n");
        fprintf(stderr, "  -com  Count comment lines\n");
        fprintf(stderr, "  -all  Count all information\n");
        return 1;
    }

    Stats stats;
    init_stats(&stats);

    if (strcmp(argv[1], "-c") == 0) {
        stats.chars = count_chars(argv[2]);
        printf("Number of characters: %d\n", stats.chars);
    } 
    else if (strcmp(argv[1], "-w") == 0) {
        stats.words = count_words(argv[2]);
        printf("Number of words: %d\n", stats.words);
    } 
    else if (strcmp(argv[1], "-s") == 0) {
        stats.sentences = count_sentences(argv[2]);
        printf("Number of sentences: %d\n", stats.sentences);
    } 
    else if (strcmp(argv[1], "-l") == 0) {
        count_basic(argv[2], &stats);
        printf("Number of lines: %d\n", stats.lines);
    } 
    else if (strcmp(argv[1], "-cl") == 0) {
        count_extended(argv[2], &stats);
        printf("Number of code lines: %d\n", stats.code_lines);
    } 
    else if (strcmp(argv[1], "-el") == 0) {
        count_extended(argv[2], &stats);
        printf("Number of empty lines: %d\n", stats.empty_lines);
    } 
    else if (strcmp(argv[1], "-com") == 0) {
        count_extended(argv[2], &stats);
        printf("Number of comment lines: %d\n", stats.comment_lines);
    } 
    else if (strcmp(argv[1], "-all") == 0) {
        count_basic(argv[2], &stats);
        count_extended(argv[2], &stats);
        printf("Number of characters: %d\n", stats.chars);
        printf("Number of words: %d\n", stats.words);
        printf("Number of sentences: %d\n", stats.sentences);
        printf("Total lines: %d\n", stats.lines);
        printf("Code lines: %d\n", stats.code_lines);
        printf("Empty lines: %d\n", stats.empty_lines);
        printf("Comment lines: %d\n", stats.comment_lines);
    } 
    else {
        fprintf(stderr, "Invalid option: %s\n", argv[1]);
        return 1;
    }

    return 0;
}